package org.scboy.rbac.service.imp;

import java.util.ArrayList;
import java.util.Date;

import java.util.List;

import org.scboy.coobi.sql.factory.EntityFactory;
import org.scboy.rbac.dao.RbacMenusDao;
import org.scboy.rbac.dao.RbacOrgResourceDao;
import org.scboy.rbac.dao.RbacPermissionDao;
import org.scboy.rbac.dao.RbacResourceDao;
import org.scboy.rbac.dao.RbacResourceMenuDao;
import org.scboy.rbac.dao.RbacResourceOrgTypeDao;
import org.scboy.rbac.dao.RbacResourcePermissionDao;
import org.scboy.rbac.dao.RbacResourceRoleTypeDao;
import org.scboy.rbac.dao.RbacResourceSysDao;
import org.scboy.rbac.dao.RbacResourceUserTypeDao;
import org.scboy.rbac.dao.RbacSystemDao;
import org.scboy.rbac.dao.RbacSystemGroupDao;
import org.scboy.rbac.dao.RbacUserResourceDao;
import org.scboy.rbac.entity.AuthorizeForm;
import org.scboy.rbac.service.ResourceService;
import org.scboy.utils.entitys.coobi.Model;
import org.scboy.utils.entitys.coobi.Page;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;


/**
 * 
 * 角色业务类
 * @author yanghao
 *
 */

@Service
public class ResourceServiceImp implements ResourceService {

	@Autowired
	EntityFactory factory;
	 /**
	   * 分页查询角色
	   * @param model 查询参数
	   * @param limit 分页参数
	   * @return
	   */	
	@Override
	public Page page(Model model) {
		RbacResourceDao dao=factory.getDao(RbacResourceDao.class);
		return dao.page(model);
	}
    
	 /**
	   * 根据角色ID获取角色
	   * @param id 角色ID
	   * @return
	   */	
	@Override
	public Model get(String id) {
		RbacResourceDao dao=factory.getDao(RbacResourceDao.class);
		return dao.get(Model.create().add("id", id));
	}
    
	 /**
	   * 新增角色
	   * @param model 角色Model
	   * @return
	   */	
	@Override
	public boolean add(Model model) {
		RbacResourceDao dao=factory.getDao(RbacResourceDao.class);
		model.add("id", UUID.randomUUID().toString());
		if(model.get("resState")==null){
			model.add("resState",0);
		}
		if(model.get("defaultResource")==null){
			model.add("defaultResource",0);
		}
		model.add("addTime", new Date());
		model.add("editTime", new Date());
		int result=dao.insert(model);
		if(result>0){
			return true;
		}else{
			return false;
		}
	}
    
	 /**
	   * 更新角色
	   * @param model 角色Model
	   * @return
	   */	
	@Override
	public boolean update(Model model) {
		RbacResourceDao dao=factory.getDao(RbacResourceDao.class);
		model.add("editTime", new Date());
		int result=dao.update(model,Model.create().add("id", model.getString("id")));
		if(result>0){
			return true;
		}else{
			return false;
		}
	}
    
	 /**
	   * 启用禁用
	   * @param id 角色ID
	   * @return
	   */	
	@Override
	public boolean checkState(String id) {
		RbacResourceDao dao=factory.getDao(RbacResourceDao.class);
		Model model=get(id);
		if(model==null){
			return false;
		}
		model.add("resState", !model.getBoolean("resState"));
		int resultCount=dao.update(model);
		if(resultCount>0){
			return true;
		}else{
			return false;
		}
	}
	
	 /**
	   * 设置取消默认
	   * @param id 角色ID
	   * @return
	   */		
	@Override
	public boolean isDefault(String id) {
		RbacResourceDao dao=factory.getDao(RbacResourceDao.class);
		Model model=get(id);
		if(model==null){
			return false;
		}
		model.add("defaultResource", !model.getBoolean("defaultResource"));
		int resultCount=dao.update(model);
		if(resultCount>0){
			return true;
		}else{
			return false;
		}
	}

	@Override
	@Transactional
	public boolean delete(String id) {
		RbacResourceDao dao=factory.getDao(RbacResourceDao.class);
		RbacResourceSysDao sysDao=factory.getDao(RbacResourceSysDao.class);
		RbacResourceMenuDao menuDao=factory.getDao(RbacResourceMenuDao.class);
		RbacResourcePermissionDao permissionDao=factory.getDao(RbacResourcePermissionDao.class);
		
		RbacOrgResourceDao orgResDao=factory.getDao(RbacOrgResourceDao.class);
		RbacUserResourceDao userResDao=factory.getDao(RbacUserResourceDao.class);
		RbacResourceUserTypeDao rut=factory.getDao(RbacResourceUserTypeDao.class);
		RbacResourceOrgTypeDao rot=factory.getDao(RbacResourceOrgTypeDao.class);
		RbacResourceRoleTypeDao rrt=factory.getDao(RbacResourceRoleTypeDao.class);
		
		Model deleteParams=Model.create().add("resId", id);
		//删除角色菜单关联
		menuDao.delete(deleteParams);
		sysDao.delete(deleteParams);
		permissionDao.delete(deleteParams);
		orgResDao.delete(deleteParams);
		userResDao.delete(deleteParams);
		rut.delete(deleteParams);
		rot.delete(deleteParams);
		rrt.delete(deleteParams);
		int result=dao.delete(Model.create().add("id", id));
		if(result>0){
			return true;
		}else{
			return false;
		}
	}


	@Override
	public List<Model> getList() {
		RbacResourceDao dao=factory.getDao(RbacResourceDao.class);
		Model params=Model.create();
		params.add("resState", true);
		params.add("defaultResource", false);
        return dao.select(params);
      
	}


	@Override
	public List<Model> getAuthorizeTree(String resId) {
		
		//系统分组
		RbacSystemGroupDao groupDao=factory.getDao(RbacSystemGroupDao.class);
		//系统配置
		RbacSystemDao systemDao=factory.getDao(RbacSystemDao.class);
		
		List<Model> groups = groupDao.select(Model.create().orderBy("sortIndex"));
		
		//可授权系统分组
		List<Model> checkGroups=new ArrayList<Model>();
		for (Model group : groups) {
			//查询分组下面启用的系统
			List<Model> systems=systemDao.select(Model.create().add("sysState", true).orderBy("sysSort"));
			List<Model> checkSystems=new ArrayList<Model>();
			for (Model system : systems) {
				
				String sysId=system.getString("id");
				//加载菜单
				List<Model> menus = getAuthorizeMenus(resId,sysId, "root");
				
				//有菜单的系统才参与授权，无菜单的系统为无效系统
				if(menus.size()>0) {
					system.add("menus", menus);
					checkSystems.add(system);
				}
			}
			
			//存在系统的分组，才可以参与授权
			if(checkSystems.size()>0) {
				group.add("systems", checkSystems);
				checkGroups.add(group);
			}
		}
		return checkGroups;
	}
	
	//循环查询权限
	public List<Model> getAuthorizeMenus(String resId,String sysId,String parentId){
		
		//菜单
		RbacMenusDao menusDao=factory.getDao(RbacMenusDao.class);
		
		//权限
		RbacPermissionDao permDao=factory.getDao(RbacPermissionDao.class);
		
		
		List<Model> mneus=menusDao.select(Model.create().add("sysId", sysId).add("parentId", parentId).add("menuAction", true).orderBy("menuSort"));
		for (Model menu : mneus) {
			
			//查询是否有权限配置
			List<Model> permissions=permDao.select(Model.create().add("menuId", menu.getString("id")).add("permAction", true).orderBy("permCode"));
			
			if(permissions.size()>0) {
				menu.add("permissions", permissions);
			}
			
			List<Model> children = getAuthorizeMenus(resId, sysId, menu.getString("id"));
			if(children.size() > 0) {
				menu.add("menus", children);
			}
		}
		return mneus;
	}
	

	@Override
	@Transactional
	public boolean authorize(AuthorizeForm params) {
		RbacResourceSysDao resSysDao=factory.getDao(RbacResourceSysDao.class);
		RbacResourceMenuDao resMenuDao=factory.getDao(RbacResourceMenuDao.class);
		RbacResourcePermissionDao resPermDao=factory.getDao(RbacResourcePermissionDao.class);
		
		//删除已经存在的权限配置。
		resMenuDao.delete(Model.create().add("resId", params.getResId()));
		resSysDao.delete(Model.create().add("resId", params.getResId()));
		resPermDao.delete(Model.create().add("resId", params.getResId()));
		
		if(params.getSysIds()!=null) {
			for (String sid : params.getSysIds()) {
				Model model=Model.create().add("id", UUID.randomUUID().toString())
						.add("resId", params.getResId())
						.add("sysId", sid)
						.add("addTime", new Date())
						.add("editTime", new Date());
				resSysDao.insert(model);
			}
		}
		
		if(params.getMenuIds()!=null) {
			for (String mid : params.getMenuIds()) {
				Model model=Model.create().add("id", UUID.randomUUID().toString())
						.add("resId", params.getResId())
						.add("menuId", mid)
						.add("addTime", new Date())
						.add("editTime", new Date());
				resMenuDao.insert(model);
			}
		}
		if(params.getPermIds()!=null) {
			for (String pid : params.getPermIds()) {
				Model model=Model.create().add("id", UUID.randomUUID().toString())
						.add("resId", params.getResId())
						.add("permId", pid)
						.add("addTime", new Date())
						.add("editTime", new Date());
				resPermDao.insert(model);
			}
		}
		
		return true;
	}

	@Override
	public Model loadAuthorize(String resId) {
		RbacResourceDao dao=factory.getDao(RbacResourceDao.class);
		Model params=Model.create().add("resId", resId);
		
		Model result=Model.create().add("resId", resId);
		
		Model systems=Model.create();
		List<Model> checkSystems= dao.getSystemCheck(params);
		for (Model cSys : checkSystems) {
			if(StrUtil.isNotEmpty(cSys.getString("id"))) {
				systems.add(cSys.getString("sysId"), true);
			}else {
				systems.add(cSys.getString("sysId"), false);
			}
		}
		Model menus=Model.create();
		List<Model> checkMenus=dao.getMenuCheck(params);
		for (Model cMenus : checkMenus) {
			if(StrUtil.isNotEmpty(cMenus.getString("id"))) {
				menus.add(cMenus.getString("menuId"), true);
			}else {
				menus.add(cMenus.getString("menuId"), false);
			}
		}
		Model permissions=Model.create();
		List<Model> checkPermissions=dao.getPermissionCheck(params);
		for (Model cPermission : checkPermissions) {
			if(StrUtil.isNotEmpty(cPermission.getString("id"))) {
				permissions.add(cPermission.getString("permId"), true);
			}else {
				permissions.add(cPermission.getString("permId"), false);
			}
		}
		result.add("sysIds", systems);
		result.add("menuIds", menus);
		result.add("permIds", permissions);
		return result;
	}

	@Override
	public Model getResourceOrg(String orgId) {
		RbacOrgResourceDao dao=factory.getDao(RbacOrgResourceDao.class);
		Model model=Model.create();
		
		List<Model> resources=dao.select(Model.create().add("orgId", orgId));
		List<String> resId=new ArrayList<String>();
		for (Model data : resources) {
			model.add("orgId", data.getString("orgId"));
			resId.add(data.getString("resId"));
		}
		model.add("resId", resId);
		return model;
	}

	@Override
	public Model getResourceUser(String userId) {
		RbacUserResourceDao dao=factory.getDao(RbacUserResourceDao.class);
		Model model=Model.create();
		List<Model> resources=dao.select(Model.create().add("userId", userId));
		List<String> resId=new ArrayList<String>();
		for (Model data : resources) {
			model.add("userId", data.getString("userId"));
			resId.add(data.getString("resId"));
		}
		model.add("resId", resId);
		return model;
	}

	@Override
	public Model getResourceOrgType(String orgTypeId) {
		RbacResourceOrgTypeDao dao=factory.getDao(RbacResourceOrgTypeDao.class);
		Model model=Model.create();
		
		List<Model> resources=dao.select(Model.create().add("orgTypeId", orgTypeId));
		List<String> resId=new ArrayList<String>();
		for (Model data : resources) {
			model.add("orgTypeId", data.getString("orgTypeId"));
			resId.add(data.getString("resId"));
		}
		model.add("resId", resId);
		return model;
	}

	@Override
	public Model getResourceUserType(String userTypeId) {
		RbacResourceUserTypeDao dao=factory.getDao(RbacResourceUserTypeDao.class);
		Model model=Model.create();
		
		List<Model> resources=dao.select(Model.create().add("userTypeId", userTypeId));
		List<String> resId=new ArrayList<String>();
		for (Model data : resources) {
			model.add("userTypeId", data.getString("userTypeId"));
			resId.add(data.getString("resId"));
		}
		model.add("resId", resId);
		return model;
	}

	@Override
	public Model getResourceRoleType(String code) {
		RbacResourceRoleTypeDao dao=factory.getDao(RbacResourceRoleTypeDao.class);
		Model model=Model.create();
		List<Model> resources=dao.select(Model.create().add("code", code));
		List<String> resId=new ArrayList<String>();
		for (Model data : resources) {
			model.add("code", data.getString("code"));
			resId.add(data.getString("resId"));
		}
		model.add("resId", resId);
		return model;
	}

	@Override
	@Transactional
	public boolean updateResourceOrg(String orgId, String[] resId) {
		RbacOrgResourceDao dao=factory.getDao(RbacOrgResourceDao.class);
		//删除配置数据
		dao.delete(Model.create().add("orgId", orgId));
		for (String rId : resId) {
			Model model=Model.create();
			model.add("id", UUID.randomUUID().toString());
			model.add("resId", rId);
			model.add("orgId", orgId);
			model.add("addTime", new Date());
			model.add("editTime", new Date());
			dao.insert(model);
		}
		return true;
	}

	@Override
	public boolean updateResourceUser(String userId, String[] resId) {
		RbacUserResourceDao dao=factory.getDao(RbacUserResourceDao.class);
		//删除配置数据
		dao.delete(Model.create().add("userId", userId));
		for (String rId : resId) {
			Model model=Model.create();
			model.add("id", UUID.randomUUID().toString());
			model.add("resId", rId);
			model.add("userId", userId);
			model.add("addTime", new Date());
			model.add("editTime", new Date());
			dao.insert(model);
		}
		return true;
	}

	@Override
	public boolean updateResourceOrgType(String orgTypeId, String[] resId) {
		RbacResourceOrgTypeDao dao=factory.getDao(RbacResourceOrgTypeDao.class);
		//删除配置数据
		dao.delete(Model.create().add("orgTypeId", orgTypeId));
		for (String rId : resId) {
			Model model=Model.create();
			model.add("id", UUID.randomUUID().toString());
			model.add("resId", rId);
			model.add("orgTypeId", orgTypeId);
			model.add("addTime", new Date());
			model.add("editTime", new Date());
			dao.insert(model);
		}
		return true;
	}

	@Override
	public boolean updateResourceUserType(String userTypeId, String[] resId) {
		RbacResourceUserTypeDao dao=factory.getDao(RbacResourceUserTypeDao.class);
		//删除配置数据
		dao.delete(Model.create().add("userTypeId", userTypeId));
		for (String rId : resId) {
			Model model=Model.create();
			model.add("id", UUID.randomUUID().toString());
			model.add("resId", rId);
			model.add("userTypeId", userTypeId);
			model.add("addTime", new Date());
			model.add("editTime", new Date());
			dao.insert(model);
		}
		return true;
	}

	@Override
	public boolean updateResourceRoleType(String code, String[] resId) {
		RbacResourceRoleTypeDao dao=factory.getDao(RbacResourceRoleTypeDao.class);
		//删除配置数据
		dao.delete(Model.create().add("code", code));
		for (String rId : resId) {
			Model model=Model.create();
			model.add("id", UUID.randomUUID().toString());
			model.add("resId", rId);
			model.add("code", code);
			model.add("addTime", new Date());
			model.add("editTime", new Date());
			dao.insert(model);
		}
		return true;
	}

	@Override
	public Page resourceOrgPage(Model params) {
		RbacOrgResourceDao dao=factory.getDao(RbacOrgResourceDao.class);
		return dao.queryPage(params);
	}

	@Override
	public Page resourceUserPage(Model params) {
		RbacUserResourceDao dao=factory.getDao(RbacUserResourceDao.class);
		return dao.queryPage(params);
	}

	@Override
	public Page resourceOrgTypePage(Model params) {
		RbacResourceOrgTypeDao dao=factory.getDao(RbacResourceOrgTypeDao.class);
		return dao.queryPage(params);
	}

	@Override
	public Page resourceUserTypePage(Model params) {
		RbacResourceUserTypeDao dao=factory.getDao(RbacResourceUserTypeDao.class);
		return dao.queryPage(params);
	}

	@Override
	public Page resourceRoleTypePage(Model params) {
		RbacResourceRoleTypeDao dao=factory.getDao(RbacResourceRoleTypeDao.class);
		return dao.queryPage(params);
	}

	@Override
	public boolean removeResourceOrg(String id) {
		RbacOrgResourceDao dao=factory.getDao(RbacOrgResourceDao.class);
		int count=dao.delete(Model.create().add("id", id));
		if(count>0) {
			return true;
		}else {
			return false;
		}
	}

	@Override
	public boolean removeResourceUser(String id) {
		RbacUserResourceDao dao=factory.getDao(RbacUserResourceDao.class);
		int count=dao.delete(Model.create().add("id", id));
		if(count>0) {
			return true;
		}else {
			return false;
		}
	}

	@Override
	public boolean removeResourceOrgType(String id) {
		RbacResourceOrgTypeDao dao=factory.getDao(RbacResourceOrgTypeDao.class);
		int count=dao.delete(Model.create().add("id", id));
		if(count>0) {
			return true;
		}else {
			return false;
		}
	}

	@Override
	public boolean removeResourceUserType(String id) {
		RbacResourceUserTypeDao dao=factory.getDao(RbacResourceUserTypeDao.class);
		int count=dao.delete(Model.create().add("id", id));
		if(count>0) {
			return true;
		}else {
			return false;
		}
	}

	@Override
	public boolean removeResourceRoleType(String id) {
		RbacResourceRoleTypeDao dao=factory.getDao(RbacResourceRoleTypeDao.class);
		int count=dao.delete(Model.create().add("id", id));
		if(count>0) {
			return true;
		}else {
			return false;
		}
	}

}
